"""Helper functions

Consists of functions to typically be used within templates, but also
available to Controllers. This module is available to both as 'h'.
"""
from webhelpers import *
from pylons import response
import random

import hashlib
from datetime import datetime
from xml.dom.minidom import getDOMImplementation

from openlbsserver.model import UserSession
from openlbsserver.model import meta
from openlbsserver.lib.error import *

from pylons import request

# FORM HELPERS

def form_input_txt(field, fieldtype='text', opts=[], checked=False, readonly=False):
    stuff = '<input id="' + str(field) + '" type="' + str(fieldtype) + '" name="' + str(field) + '" style="' + get_form_style(field) + '" '
    
    if field in request.POST and fieldtype != 'checkbox':
        stuff += 'value="' + request.POST[field] + '"'
        
        
        
    for opt in opts:
        stuff += ' ' + str(opt[0]) + '="' + str(opt[1]) + '"'
    
    if fieldtype=='checkbox' and checked == True:
        stuff += 'checked'
        
    if readonly:
        stuff += ' readonly '
    
    stuff += '/>'
    if isError(field):
        stuff += '&nbsp; ' + str(getError(field))
        
    
    return stuff

# ERROR HANDLING


# HEADING
def get_heading(heading):
    if heading == 0:
        return 'North'
    elif heading > 0 and heading < 90:
        return 'North East'
    elif heading == 90:
        return 'East'
    elif heading > 90 and heading < 180:
        return 'South East'
    elif heading == 180:
        return 'South'
    elif heading > 180 and heading < 270:
        return 'South West'
    elif heading == 270:
        return 'West'
    elif heading > 270 and heading < 360:
        return 'North West'
    else:
        return 'North'


# SESSION HANDLING
def gen_session_key():
    stuff = 'abcdefghijklmnopqrstuvwxyz0123456789'
    key = ''
    
    random.seed()
    
    for x in range(32):
        key += stuff[random.randint(0, len(stuff)-1)]
        
    m = hashlib.sha256()    
    m.update(key)
    return m.hexdigest()

def abort_invalid_session():
    setXML()
    return '<openlbs><session_error message="The session is no longer valid."/></openlbs>'

class SessionExpiredException(Exception):
    pass

def validate_session(sess_key):
    try:
        sess = meta.Session.query(UserSession).filter_by(key=sess_key).one()
        
        # expired
        if sess.expire_time < datetime.utcnow():
            meta.Session.delete(sess)
            meta.Session.commit()
            raise SessionExpiredException()
        
        return sess.device_id
        
    except:
        raise SessionExpiredException()
        
# AUTH

def auth(user, password):
    '''Validate user password'''
    try:
        m = hashlib.sha256()
        m.update(password)
        m.update(user.salt)
        if str(m.hexdigest()) == user.password:
            return True
            
    except Exception, msg:
        return False
    
    return False
    
    
# XML
def xmlFinish(doc):
    response.headers['Content-type'] = 'text/xml'
    ret = doc.toxml('utf-8')
    doc.unlink()
    return ret
    
def setXML():
    response.headers['Content-type'] = 'text/xml'

def newXML():
    impl = getDOMImplementation()
    return impl.createDocument(None, "openlbs", None)
    
def xml_loc_update_success():
    setXML()
    return '<openlbs><loc_update_success/></openlbs>'    

def abort_xml_error():
    setXML()
    return '<openlbs><error message="Invalid XML Document"/></openlbs>'
    
def xml_auth_success(secret_key='KEY', update_interval=360):
    doc = newXML()
    
    authSuccess = doc.createElement('auth_success')
    authSuccess.setAttribute('secret_key', secret_key)
    
    policy = doc.createElement('policy')
    policy.setAttribute('update_interval', str(update_interval))
    
    authSuccess.appendChild(policy)
    
    doc.documentElement.appendChild(authSuccess)
    
    return xmlFinish(doc)
    
def xml_auth_failure(msg):
    setXML()
    doc = newXML()
    
    authFailure = doc.createElement('auth_failure')
    authFailure.setAttribute('msg', msg)
    doc.documentElement.appendChild(authFailure)
    
    return xmlFinish(doc)